iT邦幫忙

2024 iThome 鐵人賽

DAY 24
0
AI/ ML & Data

使用 jq 處理資料系列 第 24

Day24: 認識 generator 概念

  • 分享至 

  • xImage
  •  

再更進一步提取更多函式之前,我們先原地調整一下,「深呼吸,慢吐氣;吸氣~吐氣~。你做的很好。」

現在的 jq 程式碼 - 最外層結構

我們首先看最外層結構的部分,參考下圖:

▼最外層結構
https://ithelp.ithome.com.tw/upload/images/20241008/20078389uo4J1oFi3i.png

認識 generator 概念

在 jq 中,generator 是一個產生多個輸出的過濾器。換句話說,它會針對單個輸入產生多個結果,而不是一次產生一個結果。當我們使用像 .[] 這樣的過濾器來處理一個陣列時,這就是一個 generator,它會針對陣列中的每個元素依次產生輸出。

常見用途:

  • 逐一取出陣列或物件:例如 .[] 會將陣列中的每個元素作為單獨的輸出。
  • 過濾器組合:如逗號 , 讓多個結果能從一個輸入生成。
  • 數據轉換和拆分:如 split() 生成多個子字串。

在認識 generator 概念之後,我們目前jq程式的最外層結構有沒有使用到 generator 呢? 🤓

編號 內容 generator
1 定義 separate(f) 函式 split()
2 將各個輸入陣列元素儲存為變數 沒有(使用slurp參數的結果)
3 組合標題陣列與每一行 AnalysisData ,.[]
4 以 TSV 格式輸出 沒有

上面整理過的編號,除了1是定義函式之外, 2 的產出(變數)是 3 的輸入,3 的產出(標題+資料)是 4 的輸入,4 產出就是最終的輸出。由此可見,我們最主要的資料處理操作,還是針對編號 3;而且從最外層的結構,我們就可以觀察到內容結果會是一行標題列[標題的固定字串]加上多行AnalysisData[AnalysisData][]的結果。

現在的 jq 程式碼 - 取得 [AnalysisData]

▼ 取得 Analysis 結構
https://ithelp.ithome.com.tw/upload/images/20241008/2007838990qpS7NaHz.png
編號 內容 generator
1 颱風陣列 .[]
2 篩選,只看山陀兒的資料 沒有
3 山陀兒路徑資料中的最近五筆 AnalysisData .[]
4 要顯示的資料內容 詳看下段

仔細觀察,在這段取得 Analysis 結構的內容當中,第一次使用 generator .[] 是在 select()之前(1 的產出是 2 的輸入,要先逐一看過颱風資料,才能從中篩選名稱是山陀兒的那一筆);第二次使用 generator .[] ,則就是要準備逐筆整理 AnalysisData 了(3 的產出是 4 的輸入,要先逐一看過每小時路徑的資料,才有辦法選到路徑的時間與方向)。

現在的 jq 程式碼 - 逐筆 AnalysisData 的整理

 [
  .fixTime[0:13], 
  separate(.coordinate)[0], 
  separate(.coordinate)[1], 
  .pressure, 
  ((.maxWindSpeed|tonumber) as $speed|$wind[]|select($speed>=.min and $speed<.max)|.level),
  ((.maxGustSpeed|tonumber) as $speed|$wind[]|select($speed>=.min and $speed<.max)|.level),
  $direction[.movingDirection], 
  .movingPrediction[0].value
 ]
  • 輸出字串陣列:因為在一開始實作的時候,我們的目標朝向最終能於 terminal 以 TSV 格式顯示;所以這個陣列基本上就是由 generator , 將各個字串組合而成。如果目標是輸出 json 格式,就會是不同的作法了。

  • 座標:使用了最外層定義的 separate 函式。因為 separate 函式有使用到 generator split() 生成多個子字串,所以這邊可以用索引[0]和[1]取得指定的字串。

  • 風速

風速這個整理的過程使用了兩次,很明顯之後可以再提取成函式💡。

首先轉型為數值 $speed,使用 generator .[]$wind 變數陣列逐一取出,再透過 $speed 符合的風速範圍篩選,以 .level 顯示結果。

((.maxWindSpeed|tonumber) as $speed|
$wind[]|
select($speed>=.min and $speed<.max)|
.level)

又一次,使用 generator .[] 是在 select()之前。

結論

今天我們認識了 generator 的概念,並且重新再回顧一次這段處理山陀兒颱風的程式碼。剛開始使用 jq 時,看到 generator 的介紹,會有一種 "我看到了,又好像沒看到" 的情況。使用一陣子之後,就會恍然大悟,jq 語法的簡潔,似乎和 generator 尤其是.[] 有著密不可分的關係! 👓

用一疊撲克牌來比喻陣列的話, generator .[] 就像是把原本疊成一疊的撲克牌展開,擺成一張一張的供人挑選。

感謝自己,今天也很認真學習。😊


上一篇
Day23: jq 自定義函式
下一篇
Day25: 將主程式寫在 main.jq 檔案中
系列文
使用 jq 處理資料30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言